package org.flexharmony.eclipse.utils;

import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.flexharmony.eclipse.HarmonyDecorator;
import org.flexharmony.eclipse.HarmonyPlugin;
import org.flexharmony.eclipse.domain.IncludedSourceFolder;
import org.flexharmony.eclipse.properties.classinclusion.IncludedSourceFolderMarshaller;

public class CommonMethods
{
  static public void projectPropertiesChanged(final IProject project) throws CoreException
  {
    Job build = new Job("FlexHarmony Builder")
    {
      @Override
      protected IStatus run(IProgressMonitor monitor)
      {
        try
        {
          project.build(IncrementalProjectBuilder.FULL_BUILD, monitor);
          return Status.OK_STATUS;
        }
        catch (CoreException cexc)
        {
          return new Status(Status.ERROR, HarmonyPlugin.PLUGIN_ID, "Harmony build failed.", cexc);
        }
      }
    };
    build.schedule();
    HarmonyDecorator.notifyConfigChange();
  }
  
  static public boolean getProjectDefaultBoolean(String propertyName, IProject project) throws CoreException
  {
    String value = getProjectDefaultProperty(propertyName, project);
    if (value == null)
    {
      return false;
    }
    else
    {
      return Boolean.parseBoolean(value);
    }
  }
  
  static public String getProjectDefaultProperty(String propertyName, IProject project) throws CoreException
  {
    String propertyValue = project.getPersistentProperty(new QualifiedName(HarmonyPlugin.PLUGIN_ID, propertyName));
    
    if (propertyValue == null)
    {
      return HarmonyPlugin.getInstance().getPluginPreferences().getString(propertyName);
    }
    else
    {
      return propertyValue;
    }
  }
  
  static public String getJavaSourceClassName(IPath sourceDir, IPath filePath)
  {
    return getClassName(sourceDir, filePath, ".java");
  }

  static public String getActionScriptClassName(IPath sourceDir, IPath filePath)
  {
    return getClassName(sourceDir, filePath, ".as");
  }

  static public boolean matches(IPath rootDirPath, IPath filePath, 
      String extension, List<String> namePatterns)
  {
    String className = getClassName(rootDirPath, filePath, extension);
    for (String namePattern : namePatterns)
    {
      if (className.matches(namePattern))
      {
        return true;
      }
    }
    
    return false;
  }
  
  static public String getClassName(IPath sourceDir, IPath filePath, String extension)
  {
    String className = filePath.removeFirstSegments(sourceDir.segmentCount()).toString();
    className = className.replace(IPath.SEPARATOR, '.').substring(0, (className.length() - extension.length()));
    return className;
  }

  static public IPath findJavaSourceRoot(IProject project, IPath javaRelativeFilePath) throws JavaModelException
  {
    IJavaProject javaProject = JavaCore.create(project);
    IClasspathEntry[] classPathEntries = javaProject.getRawClasspath();
    if (classPathEntries != null)
    {
      for (IClasspathEntry classPathEntry : classPathEntries)
      {
        if (classPathEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE)
        {
          IPath sourcePath = classPathEntry.getPath();
          IPath javaFilePath = sourcePath.append(javaRelativeFilePath).removeFirstSegments(1);
          if (project.getFile(javaFilePath).exists())
          {
            return sourcePath;
          }
        }
      }
    }
    
    return null;
  }
  
  static public boolean matchesPatterns(IProject project, IPath sourceFolderPath, IPath javaFilePath) throws CoreException
  {
    List<IncludedSourceFolder> includedFolders = IncludedSourceFolderMarshaller.unmarshall(project);
    return matchesPatterns(project, sourceFolderPath, javaFilePath, includedFolders);
  }
    
  static public boolean matchesPatterns(IProject project, IPath sourceFolderPath, IPath javaFilePath, List<IncludedSourceFolder> includedFolders) throws CoreException
  {
    if (includedFolders.size() == 0) return false;
    
    for (IncludedSourceFolder includedFolder : includedFolders)
    {
      IPath includedSourcePath = project.getFullPath().append(includedFolder.folderPath);
      if (includedSourcePath.equals(sourceFolderPath))
      {
        String javaFilePathName = javaFilePath.removeFirstSegments(sourceFolderPath.segmentCount()).toString();

        List<String> includedPatterns = includedFolder.getIncludedFilter().patterns;
        boolean includeFound;
        if (includedPatterns.size() == 0)
        {
          includeFound = true;
        }
        else
        {
          includeFound = false;
          for (String pattern : includedPatterns)
          {
            if (javaFilePathName.matches(pattern))
            {
              includeFound = true;
              break;
            }
          }
        }
        
        if (includeFound)
        {
          List<String> excludedPatterns = includedFolder.getExcludedFilter().patterns;
          boolean excludeFound = false;
          for (String pattern : excludedPatterns)
          {
            if (javaFilePathName.matches(pattern))
            {
              excludeFound = true;
              break;
            }
          }
          
          if (!excludeFound)
          {
            return true;
          }
        }
        break;
      }
    }
    
    return false;
  }

}
